<template>
  <div class="clock">
    <div class="outer-clock-face">
      <div class="marking marking-one"></div>
      <div class="marking marking-two"></div>
      <div class="marking marking-three"></div>
      <div class="marking marking-four"></div>
      <div class="inner-clock-face">
        <div class="hand hour-hand"></div>
        <div class="hand min-hand"></div>
        <div class="hand second-hand"></div>
      </div>
    </div>
  </div>
</template>

<script setup name="Clock" lang="ts">
import { ref, onMounted } from 'vue';

const secondHand = ref();
const minsHand = ref();
const hourHand = ref();

const clickEffect = () => {
  let balls:Array<Ball> = [];
  let longPressed = false;
  let longPress: ReturnType<typeof setTimeout>;
  let multiplier = 0;
  let width:number, height:number;
  let origin:{x:number,y:number};
  let normal:{x:number,y:number};
  let ctx:any;
  const colours = ['#F73859', '#14FFEC', '#00E0FF', '#FF99FE', '#FAF15D'];
  const canvas = document.createElement('canvas');
  document.body.appendChild(canvas);
  canvas.setAttribute(
    'style',
    'width: 100%; height: 100%; top: 0; left: 0; z-index: 99999; position: fixed; pointer-events: none;',
  );
  const pointer = document.createElement('span');
  pointer.classList.add('pointer');
  document.body.appendChild(pointer);

  if (canvas.getContext && window.addEventListener) {
    ctx = canvas.getContext('2d');
    updateSize();
    window.addEventListener('resize', updateSize, false);
    loop();
    window.addEventListener(
      'mousedown',
      function (e) {
        pushBalls(randBetween(10, 20), e.clientX, e.clientY);
        document.body.classList.add('is-pressed');
        longPress = setTimeout(function () {
          document.body.classList.add('is-longpress');
          longPressed = true;
        }, 500);
      },
      false,
    );
    window.addEventListener(
      'mouseup',
      function (e) {
        clearInterval(longPress);
        if (longPressed == true) {
          document.body.classList.remove('is-longpress');
          pushBalls(
            randBetween(
              50 + Math.ceil(multiplier),
              100 + Math.ceil(multiplier),
            ),
            e.clientX,
            e.clientY,
          );
          longPressed = false;
        }
        document.body.classList.remove('is-pressed');
      },
      false,
    );
    window.addEventListener(
      'mousemove',
      function (e) {
        let x = e.clientX;
        let y = e.clientY;
        pointer.style.top = y + 'px';
        pointer.style.left = x + 'px';
      },
      false,
    );
  } else {
    console.log('canvas or addEventListener is unsupported!');
  }

  function updateSize() {
    canvas.width = window.innerWidth * 2;
    canvas.height = window.innerHeight * 2;
    canvas.style.width = window.innerWidth + 'px';
    canvas.style.height = window.innerHeight + 'px';
    ctx.scale(2, 2);
    width = canvas.width = window.innerWidth;
    height = canvas.height = window.innerHeight;
    origin = {
      x: width / 2,
      y: height / 2,
    };
    normal = {
      x: width / 2,
      y: height / 2,
    };
  }
  class Ball {
    public x: number;
    public y: number;
    public angle: number;
    public multiplier: number;
    public vx: number;
    public vy: number;
    public r: number;
    public color: string;
    constructor(x = origin.x, y = origin.y) {
      this.x = x;
      this.y = y;
      this.angle = Math.PI * 2 * Math.random();
      if (longPressed == true) {
        this.multiplier = randBetween(14 + multiplier, 15 + multiplier);
      } else {
        this.multiplier = randBetween(6, 12);
      }
      this.vx = (this.multiplier + Math.random() * 0.5) * Math.cos(this.angle);
      this.vy = (this.multiplier + Math.random() * 0.5) * Math.sin(this.angle);
      this.r = randBetween(8, 12) + 3 * Math.random();
      this.color = colours[Math.floor(Math.random() * colours.length)];
    }
    update() {
      this.x += this.vx - normal.x;
      this.y += this.vy - normal.y;
      normal.x = (-2 / window.innerWidth) * Math.sin(this.angle);
      normal.y = (-2 / window.innerHeight) * Math.cos(this.angle);
      this.r -= 0.3;
      this.vx *= 0.9;
      this.vy *= 0.9;
    }
  }

  function pushBalls(count = 1, x = origin.x, y = origin.y) {
    for (let i = 0; i < count; i++) {
      balls.push(new Ball(x, y));
    }
  }

  function randBetween(min:number, max:number):number {
    return Math.floor(Math.random() * max) + min;
  }

  function loop() {
    ctx.fillStyle = 'rgba(255, 255, 255, 0)';
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for (let i = 0; i < balls.length; i++) {
      let b = balls[i];
      if (b.r < 0) continue;
      ctx.fillStyle = b.color;
      ctx.beginPath();
      ctx.arc(b.x, b.y, b.r, 0, Math.PI * 2, false);
      ctx.fill();
      b.update();
    }
    if (longPressed == true) {
      multiplier += 0.2;
    } else if (!longPressed && multiplier >= 0) {
      multiplier -= 0.4;
    }
    removeBall();
    requestAnimationFrame(loop);
  }

  function removeBall() {
    for (let i = 0; i < balls.length; i++) {
      let b = balls[i];
      if (
        b.x + b.r < 0 ||
        b.x - b.r > width ||
        b.y + b.r < 0 ||
        b.y - b.r > height ||
        b.r < 0
      ) {
        balls.splice(i, 1);
      }
    }
  }
};

onMounted(() => {
  secondHand.value = document.querySelector('.second-hand');
  minsHand.value = document.querySelector('.min-hand');
  hourHand.value = document.querySelector('.hour-hand');
  setInterval(() => {
    const now = new Date();

    const seconds = now.getSeconds();
    const secondsDegrees = (seconds / 60) * 360 + 90;
    secondHand.value.style.transform = `rotate(${secondsDegrees}deg)`;

    const mins = now.getMinutes();
    const minsDegrees = (mins / 60) * 360 + (seconds / 60) * 6 + 90;
    minsHand.value.style.transform = `rotate(${minsDegrees}deg)`;

    const hour = now.getHours();
    const hourDegrees = (hour / 12) * 360 + (mins / 60) * 30 + 90;
    hourHand.value.style.transform = `rotate(${hourDegrees}deg)`;
  }, 1000);
  clickEffect();
});
</script>

<style lang="scss" scoped>
.clock {
  width: 30rem;
  height: 30rem;
  border: 7px solid #282828;
  box-shadow: -4px -4px 10px rgba(67, 67, 67, 0.5),
    inset 4px 4px 10px rgba(0, 0, 0, 0.5),
    inset -4px -4px 10px rgba(67, 67, 67, 0.5), 4px 4px 10px rgba(0, 0, 0, 0.3);
  border-radius: 50%;
  position: relative;
  top: 50%;
  left: 50%;
  margin-top: 15rem;
  margin-left: -15rem;
  padding: 2rem;
}

.outer-clock-face {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  background: #282828;

  overflow: hidden;
}

.outer-clock-face::after {
  -webkit-transform: rotate(90deg);
  -moz-transform: rotate(90deg);
  transform: rotate(90deg);
}

.outer-clock-face::before,
.outer-clock-face::after,
.outer-clock-face .marking {
  content: '';
  position: absolute;
  width: 5px;
  height: 100%;
  background: #1df52f;
  z-index: 0;
  left: 49%;
}

.outer-clock-face .marking {
  background: #bdbdcb;
  width: 3px;
}

.outer-clock-face .marking.marking-one {
  -webkit-transform: rotate(30deg);
  -moz-transform: rotate(30deg);
  transform: rotate(30deg);
}

.outer-clock-face .marking.marking-two {
  -webkit-transform: rotate(60deg);
  -moz-transform: rotate(60deg);
  transform: rotate(60deg);
}

.outer-clock-face .marking.marking-three {
  -webkit-transform: rotate(120deg);
  -moz-transform: rotate(120deg);
  transform: rotate(120deg);
}

.outer-clock-face .marking.marking-four {
  -webkit-transform: rotate(150deg);
  -moz-transform: rotate(150deg);
  transform: rotate(150deg);
}

.inner-clock-face {
  position: absolute;
  top: 10%;
  left: 10%;
  width: 80%;
  height: 80%;
  background: #282828;
  -webkit-border-radius: 100%;
  -moz-border-radius: 100%;
  border-radius: 100%;
  z-index: 1;
}

.inner-clock-face::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 16px;
  border-radius: 18px;
  margin-left: -9px;
  margin-top: -6px;
  background: #4d4b63;
  z-index: 11;
}

.hand {
  width: 50%;
  right: 50%;
  height: 6px;
  background: #61afff;
  position: absolute;
  top: 50%;
  border-radius: 6px;
  transform-origin: 100%;
  transform: rotate(90deg);
  transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
}

.hand.hour-hand {
  width: 30%;
  z-index: 3;
}

.hand.min-hand {
  height: 3px;
  z-index: 10;
  width: 40%;
}

.hand.second-hand {
  background: #ee791a;
  width: 45%;
  height: 2px;
}
</style>
